namespace AbpPlusPlus.Evaluations
{
    using System;

    internal sealed class BinaryEvaluation : Evaluation
    {
        private readonly Evaluation _left;
        private readonly Evaluation _right;

        private readonly BinaryOperation _oper;

        public BinaryEvaluation(Evaluation left, Evaluation right, BinaryOperation oper)
        {
            this._left = left;
            this._right = right;
            this._oper = oper;
        }

        public override object Value
        {
            get
            {
                float leftValue;
                float rightValue;
                if (this._left.Value == null || this._right.Value == null)
                {
                    throw new InvalidOperationException("Either left or right value of the binary evaluation has been evaluated to null.");
                }
                if (!float.TryParse(this._left.Value.ToString(), out leftValue) ||
                    !float.TryParse(this._right.Value.ToString(), out rightValue))
                {
                    throw new InvalidOperationException("Either left or right value of the binary evaluation cannot be evaluated as a float value.");
                }
                switch (this._oper)
                {
                    case BinaryOperation.Add:
                        return leftValue + rightValue;
                    case BinaryOperation.Sub:
                        return leftValue - rightValue;
                    case BinaryOperation.Mul:
                        return leftValue * rightValue;
                    case BinaryOperation.Div:
                        return leftValue / rightValue;
                }

                throw new InvalidOperationException("Invalid binary operation.");
            }
        }

        public override string ToString() => $"{this._left} {this._oper} {this._right}";
    }
}